#pragma once
#include <string>
#include <jsoncpp/json/json.h>
#include <string.h>
#include <iostream>
#include "Socket.hpp"
using namespace SocketModule;
class Request
{
public:
    Request()
    {
    }
    Request(int x, int y, char oper) : _x(x), _y(y), _oper(oper)
    {
    }

    std::string Serialize()
    {
        // _x = 10 _y = 20, _oper = '+'
        // "10" "20" '+' : 用空格作为分隔符
        // 进行序列化
        std::string ret;
        Json::Value root;
        root["a1"] = _x;
        root["a2"] = _y;
        root["operator"] = _oper;

        Json::FastWriter writer;
        ret = writer.write(root);
        return ret;
    }

    // {"x": 10, "y" : 20, "oper" : '+'}
    bool Deserialize(std::string &in)
    {
        // "10" "20" '+' -> 以空格作为分隔符 -> 10 20 '+'
        Json::Value root;
        Json::Reader reader;
        bool ok = reader.parse(in, root);
        if (!ok)
            return false;
        _x = root["a1"].asInt();
        _y = root["a2"].asInt();
        _oper = root["operator"].asInt();
        return true;
    }
    ~Request() {}
    int X() { return _x; }
    int Y() { return _y; }
    char Oper() { return _oper; }

private:
    int _x;
    int _y;
    char _oper; // + - * / % -> _x _oper _y -> 10 + 20
};

// server -> client
class Response
{
public:
    Response() {}
    Response(int result, int code) : _result(result), _code(code)
    {
    }
    std::string Serialize()
    {
        Json::Value root;
        root["res"] = _result;
        root["code"] = _code;
        Json::FastWriter wirter;
        return wirter.write(root);
    }
    bool Deserialize(std::string &in)
    {
        Json::Value root;
        Json::Reader reader;
        bool ok = reader.parse(in, root);
        if (!ok)
            return false;
        _result = root["res"].asInt();
        _code = root["code"].asInt();
        return true;
    }
    ~Response() {}
    void Set(int result, int code)
    {
        _result = result;
        _code = code;
    }
    void ShowResult()
    {
        std::cout << "result:" << _result << " " << "code:" << _code<<std::endl;
    }

private:
    int _result; // 运算结果，无法区分清楚应答是计算结果，还是异常值
    int _code;   // 0:sucess, 1,2,3,4->不同的运算异常的情况, 约定！！！！
};
const std::string sepf = "\r\n";

using func2 = std::function<Response(Request)>;
class Protocol
{
public:
    Protocol()
    {
    }
    Protocol(func2 func5) : _func2(func5) {};
    std::string Encode(std::string mes)
    {
        // 50\r\n{"x": 10, "y" : 20, "oper" : '+'}\r\n

        // 应用层封装报头
        std::string ret;
        int len = mes.size();
        ret += std::to_string(len) + sepf + mes + sepf;
        return ret;
    }

    // 50\r\n{"x": 10, "y" : 20, "oper" : '+'}\r\n
    // 5
    // 50
    // 50\r
    // 50\r\n
    // 50\r\n{"x": 10, "
    // 50\r\n{"x": 10, "y" : 20, "oper" : '+'}\r\n
    // 50\r\n{"x": 10, "y" : 20, "oper" : '+'}\r\n50\r\n{"x": 10, "y" : 20, "ope
    //.....
    // packge故意是&
    // 1. 判断报文完整性
    // 2. 如果包含至少一个完整请求，提取他， 并从移除它，方便处理下一个
    bool Decode(std::string &buffer, std::string *packge)
    {
        auto pos = buffer.find(sepf);
        if (pos == std::string::npos)
        {
            return false;
        }
        std::string slen = buffer.substr(0, pos);
        int len = std::stoi(slen);
        int targetlen = slen.size() + 2 * sep.size() + len;
        if (buffer.size() < targetlen)
        {
            return false;
        }
        // 这里一定有一条完整请求
        *packge = buffer.substr(pos + sep.size(), len);
        buffer.erase(0, targetlen);
        return true;
    }
    // 服务端将来会需要获得需求
    void GetRequest(std::shared_ptr<Socket> sockfd, InetAddr peer)
    {
        std::string buffermessage;
        while (true)
        {
            int n = sockfd->Recive(&buffermessage);
            //std::cout << buffermessage << std::endl;
            if (n > 0)
            {
                std::string package;
                bool ret = Decode(buffermessage, &package);
                if (!ret)
                    continue;
                //std::cout << package << std::endl;
                // 此时已经获得了一个完整的报文
                // 下面进行反序列化便于我们进行业务逻辑的处理
                Request request;
                bool ok = request.Deserialize(package);

                if (!ok)
                    continue;
                // 下面业务处理交给上层处理
                Response reponse = _func2(request);

                // 把应答进行序列化
                std::string rep = reponse.Serialize();
                // 添加报头
                std::string reppackkge = Encode(rep);
                // 发送
                int n = sockfd->Send(reppackkge);
                if (n < 0)
                {
                    LOG(LogLevel::DEBUG) << "send erroe " << strerror(errno);
                }
            }
            else if (n == 0)
            {
                LOG(LogLevel::INFO) << "client:" << peer.StringAddr() << "Quit!";
                break;
            }
            else
            {
                LOG(LogLevel::WARNING) << "client:" << peer.StringAddr() << ", recv error";
                break;
            }
        }
    }
    // 客户端获得
    // 将来buffer存的是从fd读出来的数据
    bool GetResponse(std::shared_ptr<Socket> &client, std::string &buffer, Response *ret)
    {
        while (true)
        {
            int n = client->Recive(&buffer);
            if (n > 0)
            {
                // std::cout << "-----------reponse_buffer--------------" << std::endl;
                // std::cout << buffer << std::endl;
                // std::cout << "------------------------------------" << std::endl;

                std::string json_package;
                // 1. 解析报文，提取完整的json请求，如果不完整，就让服务器继续读取
                while (Decode(buffer, &json_package))
                {
                    // 我敢100%保证，我一定拿到了一个完整的报文
                    // {"x": 10, "y" : 20, "oper" : '+'} -> 你能处理吗？
                    // 2. 请求json串，反序列化
                    // std::cout << "-----------reponse_json--------------" << std::endl;
                    // std::cout << json_package << std::endl;
                    // std::cout << "------------------------------------" << std::endl;

                    // std::cout << "-----------reponse_buffer--------------" << std::endl;
                    // std::cout << buffer << std::endl;
                    // std::cout << "------------------------------------" << std::endl;

                    ret->Deserialize(json_package);
                }
                return true;
            }
            else if (n == 0)
            {
                std::cout << "server quit " << std::endl;
                return false;
            }
            else
            {
                std::cout << "recv error" << std::endl;
                return false;
            }
        }
    }
    std::string BuildRequestString(int x, int y, char c)
    {
        // 1. 构建一个完整的请求
        Request req(x, y, c);
        std::string ret1 = req.Serialize();
        return Encode(ret1);
    }
    ~Protocol()
    {
    }

private:
    func2 _func2;
};